package com.mcglib.flac
{
	
	
	
	import com.mcglib.flac.scrollBar.IScrollContainer;
	
	import flash.display.DisplayObject;
	import flash.display.MovieClip;
	import flash.display.Sprite;
	import flash.events.MouseEvent;
	import flash.geom.Rectangle;
	
	
	[Event(name="valueChange",type="com.mcglib.flac.FlacEvent")]
	[Event(name="itemClick",type="com.mcglib.flac.FlacEvent")]
	[Event(name="itemOver",type="com.mcglib.flac.FlacEvent")]
	[Event(name="itemOut",type="com.mcglib.flac.FlacEvent")]
	public class ScrollList extends FlacComponent	implements IScrollContainer
	{
		private var _dataProvide:Object  = [];
		private var _tempDataProvide:Object = [];
		private var _selectable:Boolean=true;
		private var _selectIndex:int = -1;
		private var _selectItem:*;

		/** 用于保存_IDataRendererClass类构造的实力数，与 _dataProvide中的数据量应该保存一致**/
		private var _IDataRendererVec:Vector.<IDataRenderer>=new Vector.<IDataRenderer>();
		/** 使用自己实现的Render实现类，用于控制renderUI中的数据显示 **/
		private var _rendererClass:Class;
		/** 显示列表中数据的显示UI **/
		private var _renderUIClass:Class;
		/** 当前选择的一条数据**/
		private var _selectIDataRenderer:IDataRenderer;
		
		/** 两条数据之间的空白间隔 **/
		private var _vLineGap:int=5;
		/** 列表顶部空白间隔 **/
		private var _topMargin:int=5;
		/** 列表左边空白间隔 **/
		private var _leftMargin:int=5;
		/** 一条UI显示的高度 **/
		private var _cellHeight:Number;
		/** 自定义的滚动条UI **/
		private var _showListUI:MovieClip;
		private var _container:Sprite;
		
		private var _viewScope:Rectangle;
		
		private var _proxyScrollBar:ScrollBar;
		
		/**
		 * 带滚动条的列表实现类
		 * @param scrollUI 自定义的滚动条的UI
		 * @param renderUIClass 显示列表中每一条数据的显示UI，都是通过该类来定义的
		 * @param vsbPolicy	垂直滚动条的显示策略，参照ScrollProxyList的静态常量定义
		 * @param hsbPolicy	水平滚动条的显示策略，参照ScrollProxyList的静态常量定义
		 */
		public function ScrollList(showListUI:MovieClip)
		{
			_showListUI=showListUI.list;
			var vs:MovieClip = null;
			var hs:MovieClip = null;
			try{
				vs = showListUI.getChildByName("vscroll")  as MovieClip;
				
			}catch(e:Error){
				
			}
			
			try{
				hs = showListUI.getChildByName("hscroll")  as MovieClip;	
			}catch(e:Error){
				
			}
			
			if(vs||hs){
				_proxyScrollBar = new  ScrollBar(vs,ScrollBar.SCROLLBAR_AS_NEEDED,hs,ScrollBar.SCROLLBAR_NEVER);
				_proxyScrollBar.contaienr  =  this;
			}
			
			if(_showListUI.item1==null){
				throw "作为列表数据显示的UI item1 不存在";
			}
			_renderUIClass=_showListUI.item1.constructor;//new instance.constructor;
			_topMargin=_showListUI.item1.y;
			_leftMargin=_showListUI.item1.x;
			_cellHeight=_showListUI.item1.height;
			if(_showListUI.item2){
				_vLineGap=_showListUI.item2.y-_showListUI.item1.y-_showListUI.item1.height;
				_showListUI.removeChild(_showListUI.item2);
			}
			_showListUI.removeChild(_showListUI.item1);
			
			_container=new Sprite();
			_container.x=0;
			_container.y=0;
			_container.mouseEnabled=false;
			_showListUI.addChild(_container);
			
			_viewScope=new Rectangle();
			_viewScope.x=_showListUI.x;
			_viewScope.y=_showListUI.y;
			_viewScope.height=_showListUI.height-_topMargin;
			_viewScope.width=_showListUI.width;
			resetTask();
		}
		
		public function get selectable():Boolean
		{
			return _selectable;
		}

		public function set selectable(value:Boolean):void
		{
			_selectable = value;
		}

		public function set dataProvide(value:Object):void
		{
			if(value && !(value is Array) && !(value is Vector))
				throw new Error("dataProvide只能接受Array和Vector类型");
			
			if(value is Array){
				value = (value as Array).concat();
			}else{
				var v:Vector = new Vector();
				for each(var i:* in value){
					v.push(i);
				}
				value = v;
			}
			
			_tempDataProvide = _dataProvide;
			_dataProvide= value;
		}
		
		override public function present(refresh:Boolean=true):void{
			var value:Object = _dataProvide;
			_dataProvide = _tempDataProvide;
			/*if(_dataProvide==value){
			return;
			}*/
			//清空当前的选择
			clearSelect();
			_container.y=0;
			if(_dataProvide != null && value == null){
				clearAllData();//新传进来的值和原有值都为空，则情况显示
			}else if(_dataProvide != null && value != null){
				//新传进来的值和原有值都不为空
				if(_dataProvide.length==value.length){
					_dataProvide=value;
					updateData(value);//新值的长度和原来值长度相同，则不用创建显示对象，直接更新
				}else if(_dataProvide.length<value.length){
					updateAndAdd(_dataProvide,value);//新值的长度大于原来值长度相同，更新现有UI的显示，并且增加多余部分数据的Ui
				}else if(_dataProvide.length>value.length){
					updateAndSub(_dataProvide,value);//新值的长度小于原来值长度相同，更新需要显示的部分UI数据，删除多余部分UI
				}
			}else if(_dataProvide==null && value != null){
				if(value is Array){
					_dataProvide=new Array();
				}else if(value is Vector){
					_dataProvide=new Vector();
				}
				addData(value);
			}else if(_dataProvide==null && value==null){
				clearAllData();
			}
			if(_proxyScrollBar){
				_proxyScrollBar.notifyUpdateVScroll();
				_proxyScrollBar.notifyUpdateHScroll();
			}
			
			drawLine();
		}
		
		/**
		 *清楚当前选择的数据
		 */
		public function clearSelect():void{
			if(_selectIDataRenderer){
				_selectIDataRenderer.selected = false;
			}
			_selectIDataRenderer = null;
			_selectIndex = -1;
			_selectItem = null;
		}
		/**
		 *设置当前选择的数据
		 */
		public function setSelectItem(index:int):void{
			if(_selectIDataRenderer==_IDataRendererVec[index]){
				return;
			}
			if(_selectIDataRenderer){
				_selectIDataRenderer.selected = false;
			}
			_selectIDataRenderer=_IDataRendererVec[index];
			_selectIndex = _selectIDataRenderer.itemIndex;
			_selectItem = _selectIDataRenderer.data;
			_selectIDataRenderer.selected=true;
		}
		
		/**
		 * 添加数据到显示
		 * @param data 需要添加的数据
		 */
		private function addData(data:Object):void{
			for(var i:int=0;i<data.length;i++){
				var render:IDataRenderer=addIDataRenderer(data[i],i);
				if(_dataProvide[i]==_selectItem)
				{
					render.selected = true;
					_selectIDataRenderer = render;
				}	
			}
		}
		
		/**
		 * 更新当前数据到显示
		 * @param data 需要更新的数据
		 */
		private function updateData(data:Object):void{
			for(var i:int=0;i<data.length;i++){
				var render:IDataRenderer =_IDataRendererVec[i];
				render.itemIndex = i;
				render.data = data[i];
			}
		}
		
		/**
		 * 更新已经当前显示的数据，并且添加新数据到显示
		 * @param oldData 当前显示的数据，需要被更新掉
		 * @param newData 新数据
		 */
		private function updateAndAdd(oldData:Object,newData:Object):void{
			var oldLength:int=oldData.length;
			for (var i:int = 0; i < oldLength; i++) 
			{
				var render:IDataRenderer =_IDataRendererVec[i];
				render.itemIndex = i;
				_dataProvide[i]=newData.shift();
				render.data =_dataProvide[i] ;
			}
			var leftLength:int=newData.length;
			for (var j:int = 0; j < leftLength; j++) 
			{
				addIDataRenderer(newData[j],oldLength+j);
			}
		}
		/**
		 * 更新已经当前显示的数据，并且清除多余的显示
		 * @param oldData 当前显示的数据，需要被更新掉
		 * @param newData 新数据
		 */
		private function updateAndSub(oldData:Object,newData:Object):void{
			var newLength:int=newData.length;
			for (var i:int = 0; i < newLength; i++) 
			{
				var render:IDataRenderer =_IDataRendererVec[i];
				render.itemIndex = i;
				_dataProvide[i]=newData.shift();
				render.data =_dataProvide[i] ;
			}
			var leftLength:int=oldData.length;
			for (var j:int = newLength; j < leftLength; j++) 
			{
				clearIDataRendererByIndex(newLength);
			} 
		}
		/**
		 * 清除所有显示数据
		 */
		private function clearAllData():void{
			for (var i:int = 0; i < _IDataRendererVec.length; i++) 
			{
				var render:IDataRenderer=_IDataRendererVec[i];
				clearRenderInstanceEvent(render.ui);
				clearIDataRendererByIndex(i);
			}
		}
		
		/**
		 * 添加一条新数据到指定的显示位置
		 * @param data 要添加的数据
		 * @param index 添加的位置
		 */
		private function addIDataRenderer(data:Object,index:int):IDataRenderer{
			var renderInstance:DisplayObject =new _renderUIClass();
			renderInstance.x=_leftMargin;
			renderInstance.y=_topMargin+index*(_vLineGap+renderInstance.height);
			_container.addChild(renderInstance);
			configRenderInstanceEvent(renderInstance);
			
			var render:IDataRenderer = new rendererClass();
			render.initDataRenderer(renderInstance,this);
			render.itemIndex = index;
			render.data = data;
			_IDataRendererVec.push(render);
			_dataProvide.push(data);
			return  render;
		}
		/**
		 * 清除一条指定显示位置的数据
		 * @param index 要清楚的位置
		 */
		private function clearIDataRendererByIndex(index:int):void{
			var render:IDataRenderer =_IDataRendererVec[index];
			var uiInstance:DisplayObject=render.ui;
			if(uiInstance.parent){
				uiInstance.parent.removeChild(uiInstance);
			}
			clearRenderInstanceEvent(uiInstance);
			render.clearRenderer();
			_IDataRendererVec.splice(index,1);
			_dataProvide.splice(index,1);
			uiInstance=null;
			render=null;
		}
		/**
		 * 配置显示UI的事件
		 */
		private function configRenderInstanceEvent(render:DisplayObject):void{
			render.addEventListener(MouseEvent.CLICK,onRenderInstanceClick);
			render.addEventListener(MouseEvent.MOUSE_OVER,onRenderInstanceMouseOver);
			render.addEventListener(MouseEvent.MOUSE_OUT,onRenderInstanceMouseOut);
		}
		/**
		 * 删除显示UI的事件
		 */
		private function clearRenderInstanceEvent(render:DisplayObject):void{
			render.removeEventListener(MouseEvent.CLICK,onRenderInstanceClick);
			render.removeEventListener(MouseEvent.MOUSE_OVER,onRenderInstanceMouseOver);
			render.removeEventListener(MouseEvent.MOUSE_OUT,onRenderInstanceMouseOut);
		}

		private function onRenderInstanceClick(e:MouseEvent):void{
			if(_selectable){
				var uiInstance:DisplayObject = e.currentTarget as DisplayObject;
				var render:IDataRenderer = getIDataRendererByUIInstance(uiInstance);
				if(render){
					if(_selectItem!=render.data){
						if(_selectIDataRenderer){
							_selectIDataRenderer.selected = false;
						}	
						
						render.onMouseClick(e);
						_selectIDataRenderer = render;
						_selectIDataRenderer.selected = true;
						_selectItem = render.data;
						_selectIndex=render.itemIndex;
						dispatchSelectEvent();
					}
					
					var clickEvt:FlacEvent = new FlacEvent(FlacEvent.ITEM_CLICK);
					clickEvt.value = render.data;
					clickEvt.index = render.itemIndex;
					clickEvt.render = render;
					dispatchEvent(clickEvt);
				}
			}		
		}
		
		private function onRenderInstanceMouseOver(e:MouseEvent):void{
			if(_selectable){
				var uiInstance:DisplayObject = e.currentTarget as DisplayObject;
				var render:IDataRenderer = getIDataRendererByUIInstance(uiInstance);
				if(render){
					render.onMouseOver(e);
					
					var evt:FlacEvent = new FlacEvent(FlacEvent.ITEM_OVER);
					evt.value = render.data;
					evt.index = render.itemIndex;
					evt.render = render;
					dispatchEvent(evt);
				}
			}
		}
		
		private function onRenderInstanceMouseOut(e:MouseEvent):void{
			if(_selectable){
				var uiInstance:DisplayObject = e.currentTarget as DisplayObject;
				var render:IDataRenderer = getIDataRendererByUIInstance(uiInstance);
				if(render){
					render.onMouseOut(e);	
					
					var evt:FlacEvent = new FlacEvent(FlacEvent.ITEM_OUT);
					evt.value = render.data;
					evt.index = render.itemIndex;
					evt.render = render;
					dispatchEvent(evt);
				}
			}
		}
		
		private function getIDataRendererByUIInstance(uiInstance:DisplayObject):IDataRenderer{
			for (var i:int = 0; i < _IDataRendererVec.length; i++) 
			{
				var render:IDataRenderer=_IDataRendererVec[i];
				if(render.ui==uiInstance){
					return render;
				}
			}
			return null;
		}
		
		private function dispatchSelectEvent():void{
			var e:FlacEvent = new FlacEvent(FlacEvent.VALUE_CHANGE);
			e.value = _selectItem;
			if(_selectItem && _selectIDataRenderer)
				e.index = _selectIDataRenderer.itemIndex;
			else
				e.index = -1;	
			dispatchEvent(e);
		}
		
		
		public function get dataProvide():Object
		{
			return _dataProvide;
		}

		public function getSize():int{
			if(_dataProvide==null){
				return 0;
			}
			return _dataProvide.length;
		}
		
		public function get selectItem():Object{
			return _selectItem;
		}
		
		public function get selectIndex():int{
			return _selectIndex;
		}
		
		public function getCellHeight():Number{
			return _cellHeight;
		}
		
		public function get rendererClass():Class
		{
			return _rendererClass;
		}

		public function set rendererClass(value:Class):void
		{
			_rendererClass = value;
		}

		/**
		 * 设置垂直数据之间的空白间隔
		 */
		public function set vGap(value:int):void
		{
			_vLineGap = value;
		}
		
		public function resetViewScope(rect:Rectangle):void{
			_viewScope.x=rect.x;
			_viewScope.y=rect.y;
			_viewScope.height=rect.height;
			_viewScope.width=rect.width;
		}
		
		public function resetTask():void{
			var child:DisplayObject=_showListUI.getChildByName("taskSprite");
			if(child){
				_showListUI.removeChild(child);
			}
			
			//FlacUtils.removeAllAndAdd(_showListUI);
			
			var task:Sprite=new Sprite();
			task.name="taskSprite";
			task.mouseEnabled=false;
			task.graphics.lineStyle(1, 0xff0000);
			task.graphics.beginFill(0xff0000);
			task.graphics.drawRect(_leftMargin,0,_viewScope.width,_viewScope.height+_topMargin);
			task.graphics.endFill();
			_showListUI.addChild(task);
			_showListUI.mask=task;
		}
		
		public function underControl(scrollBar:ScrollBar):void
		{
			_proxyScrollBar=scrollBar;
		}

		public function cancelControl(scrollBar:ScrollBar):void
		{
			// TODO Auto-generated method stub
		}

		public function get viewScope():Rectangle
		{
			return _viewScope;
		}
		
		public function get maxScope():Rectangle
		{
			var maxScope:Rectangle=new Rectangle();
			maxScope.x=_container.x;
			maxScope.y=_container.y;
			maxScope.width=_container.width;
			if(_container.numChildren>1){
			var lastChild:DisplayObject=_container.getChildAt(_container.numChildren-1);
			maxScope.height=lastChild.y+lastChild.height;//_container.height;
			}else{
				maxScope.height=0;
			}
			return maxScope;
		}
		
		/**
		 * @param offsetY	滚动条滑块Y轴的偏移量
		 */
		public function updateVerticalViewScope(offsetY:Number):void
		{
			_container.y=-offsetY;
		}
		/**
		 * @param offsetX	滚动条滑块X轴的偏移量
		 */
		public function updateHorizontalViewScope(offsetX:Number):void
		{
			_container.x =-offsetX;
		}
		
		public function getRenderVec():Vector.<IDataRenderer>{
			return _IDataRendererVec;
		}
		
		private function drawLine():void{
			/*_container.graphics.clear();
			
			_container.graphics.clear();
			if(_IDataRendererVec.length==0){
				return;
			}
			_container.graphics.lineStyle(1,0xFF6600);
			
			var itemMc:MovieClip=_IDataRendererVec[0].uiInstance as MovieClip;
			var x:int=itemMc.x+itemMc.ballMc.x+13;
			var y:int=itemMc.y+itemMc.ballMc.y+13;
			_container.graphics.moveTo(x,y);
			
			for (var i:int = 1; i < _IDataRendererVec.length; i++) 
			{
				itemMc=_IDataRendererVec[i].uiInstance as MovieClip;
//				point=itemMc.ballMc.localToGlobal(new Point(13,13));
				x=itemMc.x+itemMc.ballMc.x+13;
				y=itemMc.y+itemMc.ballMc.y+13;
				_container.graphics.lineTo(x,y);
			}*/
			
		}

		
	}
}